#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
#include <time.h>
#include <WiFiUdp.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>


// WiFi credentials
const char *ssid = "iPhone";        // Replace with your WiFi name
const char *password = "12345678";  // Replace with your WiFi password
// 定义GPS模块的串口连接引脚
// 修正引脚定义（ESP32-C3的硬件串口1）
#define GPS_RX_PIN 0  // ESP32的RX0接GPS模块的TX
#define GPS_TX_PIN 1  // ESP32的TX0接GPS模块的RX
// 改用硬件串口（删除SoftwareSerial）
HardwareSerial SerialGPS(1);  // 使用硬件串口1


TinyGPSPlus gps;


// MQTT Broker settings
const int mqtt_port = 8883;                                      // MQTT port (TLS)
const char *mqtt_broker = "l1097b20.ala.cn-hangzhou.emqxsl.cn";  // EMQX broker endpoint
const char *mqtt_topic = "gps";                                  // MQTT topic
const char *mqtt_username = "esp";                               // MQTT username for authentication
const char *mqtt_password = "public";                            // MQTT password for authentication



// WiFi and MQTT client initialization
WiFiClientSecure esp_client;
PubSubClient mqtt_client(esp_client);



// Load DigiCert Global Root CA ca_cert, which is used by EMQX Platform Serverless Deployment

const char *ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";


// Function Declarations
void connectToWiFi();

void connectToMQTT();

void mqttCallback(char *topic, byte *payload, unsigned int length);


void setup() {
  Serial.begin(115200);
  connectToWiFi();

  SerialGPS.begin(115200, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
  Serial.println("GPS Receiver Initialized");
  SerialGPS.setTimeout(10);  // 保持超时设置


  esp_client.setCACert(ca_cert);

  mqtt_client.setServer(mqtt_broker, mqtt_port);
  mqtt_client.setKeepAlive(60);
  mqtt_client.setCallback(mqttCallback);

  connectToMQTT();
}

void connectToWiFi() {
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to WiFi");
}

void connectToMQTT() {
  while (!mqtt_client.connected()) {
    String client_id = "esp32-client-" + String(WiFi.macAddress());
    Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());
    if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("Connected to MQTT broker");
      // mqtt_client.subscribe(mqtt_topic);
      mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");  // Publish message upon connection
    } else {
      Serial.print("Failed to connect to MQTT broker, rc=");
      Serial.print(mqtt_client.state());
      Serial.println(" Retrying in 5 seconds.");
      delay(5000);
    }
  }
}

void mqttCallback(char *topic, byte *payload, unsigned int length) {
  Serial.print("Message received on topic: ");
  Serial.println(topic);
  Serial.print("Message: ");
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println("\n-----------------------");
}


void loop() {
  if (!mqtt_client.connected()) {
    connectToMQTT();
  }
  mqtt_client.loop();

  // 调整原始数据显示方式（确保显示完整NMEA语句）
  static String rawBuffer;
  while (SerialGPS.available() > 0) {
    char c = SerialGPS.read();
    gps.encode(c);

    // 构建完整NMEA语句
    if (c == '\n') {
      Serial.print("[RAW] " + rawBuffer);
      rawBuffer = "";
    } else if (c != '\r') {
      rawBuffer += c;
    }
  }

  // 调整数据处理时机（添加延迟保证解析完成）
  static uint32_t last = 0;
  if (millis() - last >= 2000) {
    last = millis();

    Serial.print("卫星数: ");
    Serial.print(gps.satellites.value());

    if (gps.location.isValid()) {
      // 获取经纬度信息
      double latitude = gps.location.lat();
      double longitude = gps.location.lng();

      // 构建JSON格式字符串
      String jsonPayload = "{";
      jsonPayload += "\"lat\":" + String(latitude, 6);
      jsonPayload += ",\"lng\":" + String(longitude, 6);
      jsonPayload += "}";

      // 发布到MQTT
      mqtt_client.publish(mqtt_topic, jsonPayload.c_str());

      // 串口输出调试信息
      Serial.print("发送JSON数据: ");
      Serial.println(jsonPayload);
    } else {
      Serial.println("GPS信号无效");
      mqtt_client.publish(mqtt_topic, "GPS信号无效");
    }
  }
}